package com.salou.cellar.activity;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TextView;

import com.salou.cellar.R;
import com.salou.cellar.activity.helpers.Filter;
import com.salou.cellar.activity.helpers.StatisticsData;
import com.salou.cellar.contentprovider.CellarContentProvider;
import com.salou.cellar.dto.Bottle;

public class CellarVision360Activity extends Activity {
	private static final String SHOW_BOTTLES = "com.salou.cellar.showBottles";
	private static final String OPTION = "com.salou.cellar.option";
	private static final String CONFIGURE_APPLICATION = "com.salou.cellar.configure";
	private static final String FILTERS = "FILTERS";
	public static final int RESULT_ENABLE = 1;
	public static final int RESULT_CONFIG_DONE = 2;

	private CellarContentProvider ccp;

	// set of filters for the sql query
	private Bundle currentFilterSet;
	private Spinner mFilterSpinner;
	private Button mBackHierarchyButton;

	// GUI
	private TextView mHierarchy;
	private ListView mStatisticsList;
	private ArrayList<Filter> visibleFilters;
	private List<Filter> currentHierarchy;
	private ListAdapter statisticsAdapter;
	private Button mViewButton;
	private long nbBottlesSelected;
	private Button mOptionButton;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		ccp = new CellarContentProvider(getApplicationContext());
		setContentView(R.layout.vision360);
		nbBottlesSelected = getNbRows();
		if (nbBottlesSelected == 0) {
			configure();
		} else {
			initDisplay();
			refreshHierarchyAndSpinner(null);
			refreshDisplay();
		}
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.mainmenu, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// Handle item selection
		switch (item.getItemId()) {
		case R.id.configure:
			configure();
			return true;
		default:
			return super.onOptionsItemSelected(item);
		}
	}

	private void configure() {
		// When the user center presses, let them pick a contact.
		Intent intent = new Intent(CONFIGURE_APPLICATION);
		startActivityForResult(intent, RESULT_CONFIG_DONE);
	}

	private void initDisplay() {
		this.currentFilterSet = new Bundle();
		this.currentHierarchy = new ArrayList<Filter>();
		this.statisticsAdapter = new ArrayAdapter<StatisticsData>(this,
				android.R.layout.simple_list_item_single_choice,
				new StatisticsData[0]);

		// bind fields
		this.mFilterSpinner = (Spinner) findViewById(R.id.groupBySpinner);
		this.mViewButton = (Button) findViewById(R.id.viewAll);
		this.mOptionButton = (Button) findViewById(R.id.option);
		this.mHierarchy = (TextView) findViewById(R.id.hierarchy);
		this.mStatisticsList = (ListView) findViewById(R.id.repartitionList);
		this.mBackHierarchyButton = (Button) findViewById(R.id.backHierarchy);
		this.visibleFilters = new ArrayList<Filter>();
		Filter NON_SELECTED_ITEM = Filter.getInstance("selectFilter");
		NON_SELECTED_ITEM.setSelectable(false);
		
		//init filters
		for (String col : Bottle.drilldownFields) {
			Filter gbd = Filter.getInstance(col);
			gbd.setSelected(false);
		}

		// set listeners
		this.mFilterSpinner
				.setOnItemSelectedListener(new OnItemSelectedListener() {

					@Override
					public void onItemSelected(AdapterView<?> arg0, View arg1,
							int arg2, long arg3) {
						// get filter and show reparted statistics
						Filter gbd = (Filter) ((Spinner) arg0).getAdapter()
								.getItem(arg2);
						refreshStatistics(gbd);
					}

					@Override
					public void onNothingSelected(AdapterView<?> arg0) {
						refreshStatistics(null);
					}
				});

		this.mStatisticsList.setOnItemClickListener(new OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
					long arg3) {
				StatisticsData data = (StatisticsData) CellarVision360Activity.this.statisticsAdapter
						.getItem(arg2);
				Filter f = Filter.getInstance(data.field);
				f.isSelected = true;
				f.value = data.fieldValue;
				updateHierarchy(data);
			}
		});

		this.mBackHierarchyButton
				.setOnClickListener(new View.OnClickListener() {

					@Override
					public void onClick(View v) {
						List<Filter> h = CellarVision360Activity.this.currentHierarchy;
						if (h.isEmpty())
							return;
						Filter removed = h.remove(h.size() - 1);
						removed.isSelected = false;
						removed.value = null;
						currentFilterSet.remove(removed.name);
						refreshHierarchyAndSpinner(removed);
						refreshDisplay();
					}
				});
		this.mViewButton.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				startListBottlesActivity();
			}
		});
		this.mOptionButton.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				startOptionActivity();
			}
		});
	}

	private void startListBottlesActivity() {
		// When the user center presses, let them pick a contact.
		Intent intent = new Intent(SHOW_BOTTLES);
		intent.putExtra(FILTERS, this.currentFilterSet);
		startActivityForResult(intent, RESULT_ENABLE);
	}

	private void startOptionActivity() {
		// When the user center presses, let them pick a contact.
		Intent intent = new Intent(OPTION);
		intent.putExtra(FILTERS, this.currentFilterSet);
		startActivityForResult(intent, RESULT_ENABLE);
	}

	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (requestCode == RESULT_ENABLE) {
			if (resultCode == RESULT_OK) {
				// A bottle was picked.
				// startActivity(new Intent(Intent.ACTION_VIEW, data));
			}
		} else if (requestCode == RESULT_CONFIG_DONE) {
			if (resultCode == RESULT_OK) {
				// DB was reloaded, reinit display.
				initDisplay();
				refreshHierarchyAndSpinner(null);
			}
		}
		refreshDisplay();
	}

	private void refreshDisplay() {
		this.mStatisticsList.setAdapter(this.statisticsAdapter);
		nbBottlesSelected = ccp.getNbRows(currentFilterSet);
		this.mViewButton.setText(getResources().getString(R.string.viewAll,
				nbBottlesSelected));
	}

	// @param removed if not null the filter just removed by back action
	private void refreshHierarchyAndSpinner(Filter removed) {
		this.visibleFilters.clear();
		for (String col : Bottle.drilldownFields) {
			Filter gbd = Filter.getInstance(col);
			if (!gbd.isSelected)
				this.visibleFilters.add(gbd);
		}
		int ix = 0;
		if (removed != null)
			ix = this.visibleFilters.indexOf(removed);
		FilterAdapter adapt = new FilterAdapter(this, this.visibleFilters);
		this.mFilterSpinner.setAdapter(adapt);
		this.mFilterSpinner.setSelection(ix);
		this.mFilterSpinner.setPrompt(getString(R.string.spinnerLabel));
		this.mHierarchy.setText(displayHierarchy(this.currentHierarchy));
	}

	private CharSequence displayHierarchy(List<Filter> list) {
		if (list == null || list.isEmpty())
			return ">";
		StringBuffer sb = new StringBuffer();
		Iterator<Filter> it = list.iterator();
		while (it.hasNext()) {
			Filter h = it.next();
			sb.append(h.getValue());
			if (it.hasNext())
				sb.append(" > ");
		}

		return sb.toString();
	}

	// update current hierarchy displayed
	protected void updateHierarchy(StatisticsData data) {
		Filter filter = Filter.getInstance(data.field);
		this.currentHierarchy.add(filter);
		this.currentFilterSet.putString(data.field, data.fieldValue);
		this.visibleFilters.remove(filter);
		this.nbBottlesSelected = data.numberOfValues;
		refreshHierarchyAndSpinner(null);
		refreshDisplay();
	}

	protected void refreshStatistics(Filter filter) {
		List<StatisticsData> values = new ArrayList<StatisticsData>();
		if (filter != null && filter.isSelectable) {
			// get stats & display them

			Map<String, Long> stats = ccp.getStats(currentFilterSet,
					filter.name);
			if (stats == null)
				return;
			Iterator<Map.Entry<String, Long>> it = stats.entrySet().iterator();
			while (it.hasNext()) {
				Map.Entry<String, Long> entry = it.next();
				values.add(new StatisticsData(filter.name, entry.getKey(),
						entry.getValue()));
			}
		}

		sortStatistics(values);
		this.statisticsAdapter = new ArrayAdapter(this,
				android.R.layout.simple_list_item_1,
				values.toArray(new StatisticsData[] {}));
		this.mStatisticsList.setAdapter(this.statisticsAdapter);
	}

	private void sortStatistics(List<StatisticsData> values) {
		Collections.sort(values, getStatisticsComparator());
	}

	private Comparator<? super StatisticsData> getStatisticsComparator() {
		return new Comparator<StatisticsData>() {

			@Override
			public int compare(StatisticsData d1, StatisticsData d2) {
				if (d1 == null)
					return d2 == null ? 0 : -1;
				if (d2 == null)
					return 1;
				return d1.fieldValue.compareTo(d2.fieldValue);
			}

		};
	}

	private long getNbRows() {
		long nb = ccp.getNbRows(Bundle.EMPTY);
		return nb;
	}

	/**
	 * Custom adapter used to display account icons and descriptions in the
	 * account spinner.
	 */
	private class FilterAdapter extends ArrayAdapter<Filter> {
		public FilterAdapter(Context context, ArrayList<Filter> groupByData) {
			super(context, android.R.layout.simple_spinner_dropdown_item,
					groupByData);
			setDropDownViewResource(R.layout.repartition_view);
		}

		public View getDropDownView(int position, View convertView,
				ViewGroup parent) {
			// Inflate a view template
			if (convertView == null) {
				LayoutInflater layoutInflater = getLayoutInflater();
				convertView = layoutInflater.inflate(R.layout.repartition_view,
						parent, false);
			}
			TextView conceptText = (TextView) convertView
					.findViewById(R.id.conceptText);
			ImageView conceptIcon = (ImageView) convertView
					.findViewById(R.id.conceptIcon);

			// Populate template
			Filter data = getItem(position);
			conceptText.setText(data.getLabel());
			Drawable icon = data.icon;
			if (icon == null) {
				icon = getResources().getDrawable(
						android.R.drawable.ic_menu_search);
			}
			conceptIcon.setImageDrawable(icon);
			return convertView;
		}
	}
}